package com.smart.service.socket;


import cn.hutool.core.util.StrUtil;
import com.smart.common.entities.constant.SocKetTips;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Component
@Slf4j
@ServerEndpoint("/app/{id}")
public class WebSocket {

    private Session session;

    private Long id;

    private static CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>();

    private static ConcurrentHashMap<Long, Session> sessionPool = new ConcurrentHashMap<Long, Session>();


    @OnOpen
    public void onOpen(Session session, @PathParam(value = "id") Long id) {
        try {
            this.session = session;
            this.id = id;
            // 添加新连接
            webSockets.add(this);
            sessionPool.put(id, session);
            log.warn("【websocket消息】有新的连接 {}，总数为:" + webSockets.size(), id);
            sendOneMessage(id, SocKetTips.succeed);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 链接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        try {
            webSockets.remove(this);
            sessionPool.remove(this.id);
//            log.info("【websocket消息】连接断开 {}，总数为:" + webSockets.size(), this.id);
        } catch (Exception e) {
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     * @param
     */
    @OnMessage
    public void onMessage(String message) {
        try {
            if (StrUtil.equals(message, SocKetTips.heartBeat)) {
                if (session.isOpen()) {
                    session.getAsyncRemote().sendText(SocKetTips.heartBeat);
                }
            }
        } catch (Exception e) {

        }
    }

    /**
     * 发送错误时的处理
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {

        log.error("用户错误,原因:" + error);
    }


    // 此为广播消息
    public void sendAllMessage(String message) {
        log.info("【websocket消息】广播消息:" + message);
        for (WebSocket webSocket : webSockets) {
            try {
                if (webSocket.session.isOpen()) {
                    webSocket.session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 此为单点消息
    public String sendOneMessage(Long id, String message) {
        Session session = sessionPool.get(id);
        if (session != null && session.isOpen()) {
            try {
                log.info("【websocket消息】 单点消息:" + message);
                session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
                return "发送异常 发送的设备可能不在线! _异常:" + e.getMessage();
            }
            return "发送成功";
        } else {

            return "发送失败 发送的设备不在线!";
        }
    }

    // 此为单点消息(多人)
    public void sendMoreMessage(String[] ids, String message) {
        for (String id : ids) {
            Session session = sessionPool.get(id);
            if (session != null && session.isOpen()) {
                try {
                    log.info("【websocket消息】 单点消息:" + message);
                    session.getAsyncRemote().sendText(message);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
